package com.yonyou.pmclouds.basecom.util;

import com.yonyou.pmclouds.basecom.ref.itf.TreeVODependencyitf;
import com.yonyou.pmclouds.plan.entity.ScheduleItemVO;
import org.apache.commons.lang3.ArrayUtils;

import java.util.*;

/**
 * @Author chulf
 * @Date 2020/3/12
 * @Description 树形结构 回环 检测工具类
 **/
public class TreeVOCycleCheckUtil {
    public static final int VISITED_IN_PATH = 1; // 当前路径中已扫描
    public static final int VISITED_NOT_IN_PATH = -1; // 其他路径中已扫描
    private Map<String, TreeVODependencyitf> allDatas; //本次检测的所有数据


    public TreeVOCycleCheckUtil(Map<String, TreeVODependencyitf> allDatas){
        this.allDatas = allDatas;
    }

    /**
     * @author chulf
     * @date 2020/3/13
     * @Des 当返回的set 不为空则产生回环 set集合就是 pk的依赖顺序
     */
    public Set<String> getCycleRelation(TreeVODependencyitf treeVO) {

        LinkedHashMap<String, Integer> vistResult = new LinkedHashMap<>();

        dfsCheckCycle(treeVO, vistResult);

        Set<String> relationSet = vistResult.keySet();

        Iterator<String> iterator = relationSet.iterator();
        while (iterator.hasNext()){
            //删除所有 not in path 元素
            String next = iterator.next();
            if (vistResult.get(next) == VISITED_NOT_IN_PATH) iterator.remove();
        }

        return relationSet;
    }


    private boolean dfsCheckCycle(TreeVODependencyitf node, Map<String, Integer> vistResult) {
        //如果包含且 已扫描等于1
        if (vistResult.containsKey(node.findPk()) && vistResult.get(node.findPk()) == VISITED_IN_PATH) {
            return true;
        }
        //如果包含 且在其他分支中扫描
        if (vistResult.containsKey(node.findPk()) && vistResult.get(node.findPk()) == VISITED_NOT_IN_PATH) {
            return false;
        }
        //遍历分支
        vistResult.put(node.findPk(), VISITED_IN_PATH);

        TreeVODependencyitf[] treeVOS = node.findChildren();
        String[] otheDependency = node.findOtheDependency();

        if (!ArrayUtils.isEmpty(treeVOS)) {
            for (TreeVODependencyitf tempTreeVO : treeVOS) {
               if(dfsCheckCycle(tempTreeVO,vistResult)) return true;
            }
        } else if (!ArrayUtils.isEmpty(otheDependency)) {
            for (String dependencyPk : otheDependency) {
                TreeVODependencyitf treeVODependencyitf = allDatas.get(dependencyPk);
                if(treeVODependencyitf != null){
                    if(dfsCheckCycle(treeVODependencyitf,vistResult)) return true;
                }
            }
        }
        vistResult.put(node.findPk(), VISITED_NOT_IN_PATH);
        return false;
    }

    /**
     *
     * @param node
     * @return
     * @Des 检查时否将父节点设置为依赖
     */
    public boolean cehckIsParent(TreeVODependencyitf node){

        String[] otheDependency = node.findOtheDependency();

        if(ArrayUtils.isEmpty(otheDependency)) return false;

        for (String dependencyPk : otheDependency) {
            TreeVODependencyitf nodeVO = allDatas.get(dependencyPk);

            if (nodeVO != null){
                String depenDencyCode = nodeVO.findCode();

                String thisCode = node.findCode();

                if(thisCode.contains(depenDencyCode+".")) return true;
            }
        }
        return false;
    }

    /**
     *
     * @param node
     * @return
     * @Des 检查时否将子节点设置为依赖
     */
    public boolean cehckIsChild(TreeVODependencyitf node){

        String[] otheDependency = node.findOtheDependency();

        if(ArrayUtils.isEmpty(otheDependency)) return false;

        for (String dependencyPk : otheDependency) {
            TreeVODependencyitf nodeVO = allDatas.get(dependencyPk);
            if (nodeVO != null){
                String depenDencyCode = nodeVO.findCode();

                String thisCode = node.findCode();

                if(depenDencyCode.contains(thisCode+".")) return true;
            }
        }
        return false;
    }
}
